import json
import platform
import re
import shutil
import sys
import zipfile
import multiprocessing
import requests
import os
import subprocess


class DownloadClient:
    def __init__(self, interface) -> None:
        self.base_path = ""
        self.origin = {
            "lib": {
                "mojang": ["https://libraries.minecraft.net", "https://maven.minecraftforge.net"],
                "mcbbs": "https://download.mcbbs.net/maven",
                "bmclapi2": "https://bmclapi2.bangbang93.com/maven"
            },
            "ass": {
                "mojang": "https://resources.download.minecraft.net",
                "mcbbs": "https://download.mcbbs.net/assets",
                "bmclapi2": "https://bmclapi2.bangbang93.com/assets"
            },
            "data": {
                "mojang": ["https://launcher.mojang.com", "https://launcher.mojang.com", "https://piston-data.mojang.com"],
                "mcbbs": "https://download.mcbbs.net",
                "bmclapi2": "https://bmclapi2.bangbang93.com"
            },
            "allver": {
                "mojang": "https://launchermeta.mojang.com/mc/game/version_manifest_v2.json",
                "mcbbs": "https://download.mcbbs.net/mc/game/version_manifest_v2.json",
                "bmclapi2": "https://bmclapi2.bangbang93.com/mc/game/version_manifest_v2.json"
            },
            "fabric-meta": {
                "fabric": "https://meta.fabricmc.net",
                "mcbbs": "https://download.mcbbs.net/fabric-meta",
                "bmclapi2": "https://bmclapi2.bangbang93.com/fabric-meta"
            },
            "fabric-maven": {
                "fabric": "https://maven.fabricmc.net",
                "mcbbs": "https://download.mcbbs.net/maven",
                "bmclapi2": "https://bmclapi2.bangbang93.com/maven"
            },
            "forge-maven": {
                "forge": "https://files.minecraftforge.net",
                "mcbbs": "https://download.mcbbs.net",
                "bmclapi2": "https://bmclapi2.bangbang93.com"
            },
            "forge-lib": {
                "forge": "https://maven.minecraftforge.net",
                "mcbbs": "https://download.mcbbs.net/maven",
                "bmclapi2": "https://bmclapi2.bangbang93.com/maven"
            }
        }
        self.version = ""
        self.name = ""
        self.version_json = {}
        self.lib_origin = "mojang"
        self.ass_origin = "mojang"
        self.data_origin = "mojang"
        self.allver_origin = "mojang"
        self.interface = interface
        self.all_version_info = requests.get(
            self.origin["allver"][self.allver_origin]).json()
        self.callback_queue = multiprocessing.Queue()
        self.cb_qtSig = None
        self.launcher_profile = {
            "profiles":  {
                "QMCL": {
                    "name": "QMCL"
                }
            },
            "selectedProfile": "QMCL",
            "clientToken": "QMCLQMCLQMCLQMCLQMCLQMCLQMCLQMCL"
        }

    def launcher_profiles(self):
        try:
            pf = open(os.path.join(self.base_path, "launcher_profiles.json"), 'x', encoding="utf-8")
            pf.write(self.launcher_profile)
            pf.close()
        except FileExistsError:
            pass

    def replace_url(self, url: str, o1, o2):
        if type(o1) == list:
            for i in o1:
                url = url.replace(i, o2)
            return url
        else:
            return url.replace(o1, o2)

    def makrdir(self):
        os.makedirs(os.path.join(self.base_path, self.name))

    def getJson(self):
        for version_info in self.all_version_info["versions"]:
            if version_info["id"] == self.version:
                self.version_json = requests.get(version_info["url"]).json()
                return True
        return False

    def refreshVersionList(self):
        self.all_version_info = requests.get(
            self.origin["allver"][self.allver_origin]).json()

    def getLibraries(self):
        self.version_json["libraries"]

    def get_os_version(self):
        if platform.system() == "Windows":
            ver = sys.getwindowsversion()
            return f"{ver.major}.{ver.minor}"
        elif platform.system == "Darwin":
            return ""
        else:
            return platform.uname().release

    def parse_single_rule(self, rule, options):
        if rule["action"] == "allow":
            returnvalue = False
        elif rule["action"] == "disallow":
            returnvalue = True
        if "os" in rule:
            for key, value in rule["os"].items():
                if key == "name":
                    if value == "windows" and platform.system() != 'Windows':
                        return returnvalue
                    elif value == "osx" and platform.system() != 'Darwin':
                        return returnvalue
                    elif value == "linux" and platform.system() != 'Linux':
                        return returnvalue
                elif key == "arch":
                    if value == "x86" and platform.architecture()[0] != "32bit":
                        return returnvalue
                elif key == "version":
                    if not re.match(value, self.get_os_version()):
                        return returnvalue
        if "features" in rule:
            for key, value in rule["features"].items():
                if key == "has_custom_resolution" and not options.get("customResolution", False):
                    return returnvalue
                elif key == "is_demo_user" and not options.get("demo", False):
                    return returnvalue
        return not returnvalue

    def parse_rule_list(self, data, rule_string, options) -> bool:
        if rule_string not in data:
            return True
        for i in data[rule_string]:
            if not self.parse_single_rule(i, options):
                return False
        return True

    def getNatives(self, data) -> str:
        if platform.architecture()[0] == "32bit":
            arch_type = "32"
        else:
            arch_type = "64"
        if "natives" in data:
            if platform.system() == 'Windows':
                if "windows" in data["natives"]:
                    return data["natives"]["windows"].replace("${arch}", arch_type)
                else:
                    return ""
            elif platform.system() == 'Darwin':
                if "osx" in data["natives"]:
                    return data["natives"]["osx"].replace("${arch}", arch_type)
                else:
                    return ""
            else:
                if "linux" in data["natives"]:
                    return data["natives"]["linux"].replace("${arch}", arch_type)
                else:
                    return ""
        else:
            return ""

    def extract_natives_file(self, filename: str, extract_path: str, extract_data) -> None:
        try:
            os.mkdir(extract_path)
        except Exception:
            pass
        zf = zipfile.ZipFile(filename, "r")
        for i in zf.namelist():
            for e in extract_data["exclude"]:
                if i.startswith(e):
                    break
            else:
                zf.extract(i, extract_path)

    def install_libraries(self, data: dict, path: str) -> None:
        self.callback_queue.put(
            "[all]->lib " + str(len(data["libraries"]) - 1))
        for count, i in enumerate(data["libraries"]):

            if not self.parse_rule_list(i, "rules", {}):
                continue

            currentPath = os.path.join(path, "libraries")
            if "url" in i:
                if i["url"].endswith("/"):
                    downloadUrl = i["url"][:-1]
                else:
                    downloadUrl = i["url"]
            else:
                downloadUrl = self.origin["lib"][self.lib_origin]
            try:
                libPath, name, version = i["name"].split(":")[0:3]
            except ValueError:
                continue
            for libPart in libPath.split("."):
                currentPath = os.path.join(currentPath, libPart)
                downloadUrl = downloadUrl + "/" + libPart
            try:
                version, fileend = version.split("@")
            except ValueError:
                fileend = "jar"
            jarFilename = name + "-" + version + "." + fileend
            downloadUrl = downloadUrl + "/" + name + "/" + version
            currentPath = os.path.join(currentPath, name, version)
            native = self.getNatives(i)

            if native != "":
                jarFilenameNative = name + "-" + version + "-" + native + ".jar"
            jarFilename = name + "-" + version + "." + fileend
            downloadUrl = downloadUrl + "/" + jarFilename

            try:
                self.interface("Download.TDownload").download_file(
                    downloadUrl, os.path.join(currentPath, jarFilename), 5, i["size"])
                self.callback_queue.put("[download] " + downloadUrl)
            except Exception:
                pass
            if "downloads" not in i:
                if "extract" in i:
                    self.extract_natives_file(os.path.join(currentPath, jarFilenameNative), os.path.join(
                        path, "versions", self.name, "natives"), i["extract"])
                continue
            if "artifact" in i["downloads"]:
                self.interface("Download.TDownload").download_file(self.replace_url(i["downloads"]["artifact"]["url"], self.origin["lib"]["mojang"], self.origin["lib"][self.lib_origin]), os.path.join(
                    path, "libraries", i["downloads"]["artifact"]["path"]), 5, i["downloads"]["artifact"]["size"])
                self.callback_queue.put("[download] " + self.replace_url(i["downloads"]["artifact"]
                                        ["url"], self.origin["lib"]["mojang"], self.origin["lib"][self.lib_origin]), True)
            if native != "":
                self.interface("Download.TDownload").download_file(self.replace_url(i["downloads"]["classifiers"][native]["url"], self.origin["lib"]["mojang"], self.origin["lib"][self.lib_origin]), os.path.join(
                    currentPath, jarFilenameNative), 5, i["downloads"]["classifiers"][native]["size"])
                self.callback_queue.put("[download] " + self.replace_url(i["downloads"]["classifiers"]
                                        [native]["url"], self.origin["lib"]["mojang"], self.origin["lib"][self.lib_origin]), True)
                if "extract" in i:
                    self.extract_natives_file(os.path.join(currentPath, jarFilenameNative), os.path.join(
                        path, "versions", self.name, "natives"), i["extract"])
                    self.callback_queue.put(
                        "[extract] " + os.path.join(currentPath, jarFilenameNative), True)

    def install_assets(self, data, path: str, checkmode=False) -> None:
        if "assetIndex" not in data:
            return
        try:
            os.makedirs(os.path.join(path, "assets", "indexes"))
        except Exception:
            pass
        with open(os.path.join(path, "assets", "indexes", data["assets"] + ".json"), "wb+") as f:
            assets_index = requests.get(data["assetIndex"]["url"])
            f.write(assets_index.content)
            assets_data = assets_index.json()
            self.callback_queue.put(
                "[download] " + data["assetIndex"]["url"], True)
        use_list = []
        use_path_list = []
        use_size_list = []
        for key, value in assets_data["objects"].items():
            use_list.append(
                self.origin["ass"][self.ass_origin] + "/" + value["hash"][:2] + "/" + value["hash"])
            use_path_list.append(os.path.join(
                path, "assets", "objects", value["hash"][:2], value["hash"]))
            use_size_list.append(value["size"])
        if checkmode:
            self.interface("Download.PDownload").download_file(
                use_list, use_path_list, 4, 10, use_size_list)
            return
        self.interface("Download.PDownload").download_file(
            use_list, use_path_list, 4, 10, use_size_list, self.callback_queue)

    def install_jar(self, data, path: str):
        self.interface("Download.TDownload").download_file(self.replace_url(data["downloads"]["client"]["url"], self.origin["data"]["mojang"], self.origin["data"][self.data_origin]), os.path.join(
            path, "versions", self.name, self.name + ".jar"), 3, data["downloads"]["client"]["size"], self.callback_queue)
        self.install_logging(data, path)

    def install_logging(self, data, path: str):
        if "logging" in data:
            if len(data["logging"]) != 0:
                self.interface("Download.TDownload").download_file(self.replace_url(data["logging"]["client"]["file"]["url"], self.origin["data"]["mojang"], self.origin["data"][self.data_origin]), os.path.join(
                    path, "assets", "log_configs", data["logging"]["client"]["file"]["id"]), 2, data["logging"]["client"]["file"]["size"], self.callback_queue)

    def callback(self):
        while True:
            try:
                cb = self.callback_queue.get(True, 5)
                print(cb)
            except Exception:
                return

    def install_client(self):
        if not self.version_json:
            self.getJson()
        if self.version_json:
            try:
                os.makedirs(os.path.join(
                    self.base_path, "versions", self.name))
            except FileExistsError:
                pass
            with open(os.path.join(self.base_path, "versions", self.name, self.name + ".json"), "w", encoding="utf-8") as f:
                self.version_json["id"] = self.name
                f.write(json.dumps(self.version_json))
            self.lib_origin = "mcbbs"
            self.ass_origin = "mcbbs"
            self.data_origin = "mcbbs"
            callback_ps = multiprocessing.Process(target=self.callback)
            callback_ps.start()
            instlib_ps = multiprocessing.Process(
                target=self.install_libraries, args=(self.version_json, self.base_path))
            instlib_ps.start()
            instass_ps = multiprocessing.Process(
                target=self.install_assets, args=(self.version_json, self.base_path))
            instass_ps.start()
            instjar_ps = multiprocessing.Process(
                target=self.install_jar, args=(self.version_json, self.base_path))
            instjar_ps.start()
        else:
            print("version notfound", self.version)


class DownloadFabric(DownloadClient):
    def __init__(self, interface) -> None:
        super(DownloadFabric, self).__init__(interface)
        self.all_loader_version_info = False
        self.latest_loader_version = False
        self.latest_installer_version = False
        self.fme_origin = "fabric"
        self.fma_origin = "fabric"
        self.java_path = "java"

    def get_latest_loader_version(self) -> str:
        self.latest_loader_version = self.all_loader_version_info[0]["version"]

    def get_all_loader_versions(self):
        self.all_loader_version_info = requests.get(
            self.origin["fabric-meta"][self.fme_origin] + "/v2/versions/loader").json()

    def parse_maven_metadata(self, data: str):
        r = {}

        r["release"] = re.search(
            "(?<=<release>).*?(?=</release>)", data, re.MULTILINE).group()
        r["latest"] = re.search(
            "(?<=<latest>).*?(?=</latest>)", data, re.MULTILINE).group()
        r["versions"] = re.findall(
            "(?<=<version>).*?(?=</version>)", data, re.MULTILINE)
        return r

    def get_latest_installer_version(self) -> str:
        self.latest_installer_version = self.parse_maven_metadata(requests.get(
            self.origin["fabric-maven"][self.fma_origin] + "/net/fabricmc/fabric-installer/maven-metadata.xml").text)["latest"]

    def install_loader(self) -> None:
        """
        Install a fabric version
        """
        if not self.latest_loader_version:
            self.get_all_loader_versions()
            self.get_latest_loader_version()
        if not self.latest_installer_version:
            self.get_latest_installer_version()
        installer_download_url = self.origin["fabric-maven"][self.fma_origin] + \
            f"/net/fabricmc/fabric-installer/{self.latest_installer_version}/fabric-installer-{self.latest_installer_version}.jar"
        try:
            os.makedirs(".\\.core_temp")
        except FileExistsError:
            pass
        installer_path = os.path.join(
            ".\\.core_temp", f"fabric-installer-{self.latest_installer_version}.jar")

        with open(installer_path, "wb") as f:
            f.write(requests.get(installer_download_url).content)

        command = [self.java_path, "-jar", installer_path, "client", "-dir", self.base_path,
                   "-mcversion", self.version, "-loader", self.latest_loader_version, "-noprofile", "-snapshot"]
        exitcode = subprocess.Popen(command, stdout=open(
            "log.log", "w", encoding="utf-8"), stderr=open("err.log", "w", encoding="utf-8")).wait()
        if exitcode != 0:
            print("Fabric install failed!")
            return

        os.remove(installer_path)
        os.removedirs(".\\.core_temp")
        with open(os.path.join(self.base_path, "versions", f"fabric-loader-{self.latest_loader_version}-{self.version}", f"fabric-loader-{self.latest_loader_version}-{self.version}.json"), 'r', encoding="utf-8") as fabric_version_json:
            fabric_version_json = json.loads(fabric_version_json.read())
        with open(os.path.join(self.base_path, "versions", self.name, self.name + ".json"), 'r', encoding="utf-8") as custom_version_json:
            custom_version_json = json.loads(custom_version_json.read())
        custom_version_json["mainClass"] = fabric_version_json["mainClass"]
        custom_version_json["libraries"] += fabric_version_json["libraries"]
        with open(os.path.join(self.base_path, "versions", self.name, self.name + ".json"), 'w', encoding="utf-8") as crafted_version_json:
            crafted_version_json.write(json.dumps(custom_version_json))
        os.remove(os.path.join(self.base_path, "versions",
                  f"fabric-loader-{self.latest_loader_version}-{self.version}", f"fabric-loader-{self.latest_loader_version}-{self.version}.json"))
        os.remove(os.path.join(self.base_path, "versions",
                  f"fabric-loader-{self.latest_loader_version}-{self.version}", f"fabric-loader-{self.latest_loader_version}-{self.version}.jar"))
        os.removedirs(os.path.join(self.base_path, "versions",
                      f"fabric-loader-{self.latest_loader_version}-{self.version}"))


class DownloadForge(DownloadClient):
    def __init__(self, interface) -> None:
        super(DownloadForge, self).__init__(interface)
        self.forge_version = False
        self.fma_origin = "forge"
        self.java_path = None
        self.zf = False

    def install_forge_libraries(self, data, path: str):
        for lib in data["libraries"]:
            self.interface("Download.TDownload").download_file(self.replace_url(lib["downloads"]["artifact"]["url"], self.origin["lib"]["mojang"], self.origin["lib"][self.lib_origin]), os.path.join(
                path, "libraries", lib["downloads"]["artifact"]["path"]), 3, lib["downloads"]["artifact"]["size"], another_origin=lib["downloads"]["artifact"]["url"])

    def parse_maven_metadata(self, data: str):
        r = {}

        r["release"] = re.search(
            "(?<=<release>).*?(?=</release>)", data, re.MULTILINE).group()
        r["latest"] = re.search(
            "(?<=<latest>).*?(?=</latest>)", data, re.MULTILINE).group()
        r["versions"] = re.findall(
            "(?<=<version>).*?(?=</version>)", data, re.MULTILINE)
        return r

    def list_forge_versions(self):
        """
        Returns a list of all forge versions
        """
        return self.parse_maven_metadata(requests.get(self.origin["forge-maven"][self.fma_origin] + "/maven/net/minecraftforge/forge/maven-metadata.xml").text)["versions"]

    def find_forge_version(self):
        """
        Find the latest forge version that is compatible to the given vanilla version
        """
        version_list = self.list_forge_versions()
        for i in version_list:
            version_split = i.split("-")
            if version_split[0] == self.version:
                self.forge_version = i
                return
        self.forge_version = False
    
    def extract_file(self, zip_path: str, extract_path: str) -> None:
        """
        Extract a file from a zip handler into the given path
        """
        try:
            os.makedirs(os.path.dirname(extract_path))
        except Exception:
            pass
        with self.zf.open(zip_path, "r") as f:
            with open(extract_path, "wb") as w:
                w.write(f.read())

    def get_data_library_path(self, libname: str, path: str) -> str:
        """
        Turns the libname into a path
        """
        # Remove the []
        libname = libname[1:-1]
        libpath = os.path.join(path, "libraries")
        base_path, libname, version, extra = libname.split(":")
        for i in base_path.split("."):
            libpath = os.path.join(libpath, i)
        try:
            extra, fileend = extra.split("@")
        except ValueError:
            fileend = "jar"
        libpath = os.path.join(libpath, libname, version, libname + "-" + version + "-" + extra + "." + fileend)
        return libpath

    def get_library_path(self, name: str, path: str) -> str:
        """
        Returns the path from a libname
        """
        libpath = os.path.join(path, "libraries")
        parts = name.split(":")
        base_path, libname, version = parts[0:3]
        for i in base_path.split("."):
            libpath = os.path.join(libpath, i)
        try:
            version, fileend = version.split("@")
        except ValueError:
            fileend = "jar"

        # construct a filename with the remaining parts
        filename = f"{libname}-{version}{''.join(map(lambda p: f'-{p}', parts[3:]))}.{fileend}"
        libpath = os.path.join(libpath, libname, version, filename)
        return libpath

    def get_jar_mainclass(self, path: str) -> str:
        """
        Returns the mainclass of a given jar
        """
        zf = zipfile.ZipFile(path)
        # Parse the MANIFEST.MF
        with zf.open("META-INF/MANIFEST.MF") as f:
            lines = f.read().decode("utf-8").splitlines()
        zf.close()
        content = {}
        for i in lines:
            try:
                key, value = i.split(":")
                content[key] = value[1:]
            except Exception:
                pass
        return content["Main-Class"]

    def forge_processors(self, data, minecraft_directory, lzma_path: str, installer_path: str, java: str = None) -> None:
        """
        Run the processors of the install_profile.json
        """
        path = str(minecraft_directory)
        argument_vars = {"{MINECRAFT_JAR}": os.path.join(path, "versions", data["minecraft"], data["minecraft"] + ".jar")}
        for key, value in data["data"].items():
            if value["client"].startswith("[") and value["client"].endswith("]"):
                argument_vars["{" + key + "}"] = self.get_data_library_path(value["client"], path)
            else:
                argument_vars["{" + key + "}"] = value["client"]
        root_path = os.path.join(".\\.core_temp\\forge-root")
        argument_vars["{INSTALLER}"] = installer_path
        argument_vars["{BINPATCH}"] = lzma_path
        argument_vars["{ROOT}"] = root_path
        argument_vars["{SIDE}"] = "client"
        if platform.system() == "Windows":
            classpath_seperator = ";"
        else:
            classpath_seperator = ":"
        for count, i in enumerate(data["processors"]):
            if "client" not in i.get("sides", ["client"]):
                # Skip server side only processors
                continue
            # Get the classpath
            classpath = ""
            for c in i["classpath"]:
                classpath = classpath + self.get_library_path(c, path) + classpath_seperator
            classpath = classpath + self.get_library_path(i["jar"], path)
            mainclass = self.get_jar_mainclass(self.get_library_path(i["jar"], path))
            command = [java or "java", "-cp", classpath, mainclass]
            for c in i["args"]:
                try:
                    var = argument_vars[c]
                except KeyError:
                    var = c
                if var.startswith("[") and var.endswith("]"):
                    command.append(self.get_library_path(var[1:-1], path))
                else:
                    command.append(var)
            for key, value in argument_vars.items():
                for pos in range(len(command)):
                    command[pos] = command[pos].replace(key, value)
            subprocess.call(command)
        if os.path.exists(root_path):
            shutil.rmtree(root_path)
    
    def download_file(self, url: str, path: str):
        try:
            os.makedirs(os.path.dirname(path))
        except FileExistsError:
            pass
        with open(path, 'wb') as f:
            f.write(requests.get(url).content)

    def install_forge_version(self) -> None:
        """
        Installs a forge version. Fore more information look at the documentation.
        """
        self.getJson()
        if not self.forge_version:
            self.find_forge_version()
        if not self.forge_version:
            print("don't support!")
            return
        installer_path = os.path.join(f".\\.core_temp\\forge-{self.forge_version}-installer.jar")
        self.download_file(self.origin["forge-maven"][self.fma_origin] + f"/maven/net/minecraftforge/forge/{self.forge_version}/forge-{self.forge_version}-installer.jar", installer_path)
        self.zf = zipfile.ZipFile(installer_path, "r")
        # Read the install_profile.json
        with self.zf.open("install_profile.json", "r") as f:
            version_data = json.loads(f.read())
            version_data["minecraft"] = self.name
        self.install_forge_libraries(version_data, self.base_path)
        # Extract the version.json
        version_json_path = os.path.join(self.base_path, "versions", self.name, self.name + ".json")
        self.extract_file("version.json", version_json_path)
        with open(version_json_path, 'r', encoding="utf-8") as f:
            self.forge_version_json = json.loads(f.read())
        with open(version_json_path, 'w', encoding="utf-8") as f:
            self.forge_version_json["inheritsFrom"] = self.name
            self.forge_version_json["id"] = self.name
            self.forge_version_json["libraries"] += self.version_json["libraries"]
            f.write(json.dumps(self.forge_version_json))
        # Extract forge libs from the installer
        forge_lib_path = os.path.join(self.base_path, "libraries", "net", "minecraftforge", "forge", self.forge_version)
        try:
            self.extract_file("maven/net/minecraftforge/forge/{version}/forge-{version}.jar".format(version=self.forge_version), os.path.join(forge_lib_path, "forge-" + self.forge_version + ".jar"))
            self.extract_file("maven/net/minecraftforge/forge/{version}/forge-{version}-universal.jar".format(version=self.forge_version), os.path.join(forge_lib_path, "forge-" + self.forge_version + "-universal.jar"))
        except KeyError:
            pass
        # Extract the client.lzma
        lzma_path = os.path.join(".\\.core_temp\\client.lzma")
        try:
            self.extract_file("data/client.lzma", lzma_path)
        except KeyError:
            pass
        self.zf.close()
        self.forge_processors(version_data, self.base_path, lzma_path, installer_path, self.java_path)
        # os.remove(os.path.join(self.base_path, "versions", self.forge_version, self.forge_version + ".json"))
        # os.removedirs(os.path.join(self.base_path, "versions", self.forge_version))
        # os.remove(installer_path)
        # os.removedirs(".\\.core_temp")

class DownloadServer(DownloadClient):
    def __init__(self, interface) -> None:
        super(DownloadServer, self).__init__(interface)

    def install_server(self):
        self.getJson()
        if self.version_json:
            if "server" not in self.version_json["downloads"].keys():
                print("this version haven't server")
                return
            self.interface("Download.TDownload").download_file(self.replace_url(self.version_json["downloads"]["server"]["url"], self.origin["data"]["mojang"], self.origin["data"][self.data_origin]), os.path.join(
                self.base_path, "server_versions", self.name, self.name + ".jar"), 4, self.version_json["downloads"]["server"]["size"], self.callback_queue)
        else:
            print("version notfound", self.version)
